/**
 * @class Ext.grid.Section
 * @extends Ext.panel.Panel
 *
 * Section of a Grid. Headers are docked in this area and this class
 * synchronizes the viewable area and headers.
 *
 * Locked Sections
 * - cannot flex headers.
 * - must have a fixed width
 *
 * Virtualized (non locked) or Scrollable Sections must be synchronized vertically.
 *
 * Sections can resize based off of header size/visibility changes.
 *
 * Templates can become dirty based off of visibility changes.
 */

Ext.define('Ext.grid.Section', {
    extend: 'Ext.panel.Panel',
    requires: [
        'Ext.grid.View',
        'Ext.grid.HeaderContainer'
    ],
    alias: 'widget.gridsection',

    layout: 'fit',
    cls: Ext.baseCSSPrefix + 'grid-section',
    isGridSection: true,
    scroll: true,
    border: false,
    
    verticalScrollDock: 'right',
    extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
    
    scrollDelta: 40,
    
    
    /**
     * Boolean to indicate that GridView has been injected into this Grid Section.
     * @property hasGridView
     */
    hasGridView: false,
    
    // TODO: Rename headers -> columns
    
    initComponent: function() {
        // TODO: Remove in the future.
        if (!this.locked) {
            this.flex = 1;
        }
        
        this.bodyCls = this.bodyCls || '';
        this.bodyCls += (' ' + this.extraBodyCls);

        this.dockedItems = this.dockedItems || [];
        var scroll     = this.scroll,
            vertical   = false,
            horizontal = false;
            
        // turn both on.
        if (scroll === true || scroll === 'both') {
            vertical = horizontal = true;
        } else if (scroll === 'horizontal') {
            horizontal = true;
        } else if (scroll === 'vertical') {
            vertical = true;
        }
        // All other values become 'none' or false.
        
        
        if (vertical) {
            this.verticalScroller = Ext.ComponentMgr.create({
                dock: this.verticalScrollDock,
                xtype: 'gridscroller'
            });
        }
        
        if (horizontal) {
            this.horizontalScroller = Ext.ComponentMgr.create({
                xtype: 'gridscroller',
                section: this,
                dock: 'bottom'
            });
        }
        
        /**
         * @property headerCt -> colModel?
         */
        this.headerCt = new Ext.grid.HeaderContainer({
            items: this.headers
        });
        this.headerCt.on('headerresize', this.onHeaderResize, this);
        
        this.features = this.features || [];
        this.dockedItems = this.dockedItems || [];
        this.dockedItems.unshift(this.headerCt);
       
        Ext.grid.Section.superclass.initComponent.call(this);
    },
    
    determineScrollbars: function() {
        if (!this.dtScrollTask) {
            this.dtScrollTask = new Ext.util.DelayedTask(this.doDetermineScrollbars, this);
        }
        this.dtScrollTask.delay(30);
    },
    
    doDetermineScrollbars: function() {
        if (this.view) {
            var viewElDom             = this.view.el.dom,
                centerScrollWidth = viewElDom.scrollWidth,
                // clientWidth often returns 0 in IE resulting in an
                // infinity result, here we use offsetWidth bc there are
                // no possible scrollbars and we dont care about margins
                centerClientWidth = viewElDom.offsetWidth,
                scrollHeight = viewElDom.scrollHeight,
                clientHeight = viewElDom.clientHeight;
                
            if (scrollHeight > clientHeight) {
                this.showVerticalScroller();
            } else {
                this.hideVerticalScroller();
            }
            
    
            if (centerScrollWidth > (centerClientWidth + Ext.getScrollBarWidth() - 2)) {
                this.showHorizontalScroller();
            } else {
                this.hideHorizontalScroller();
            }
        }
    },
    
    onHeaderResize: function() {
        if (this.view) {
            this.determineScrollbars();
            this.up('gridpanel').invalidateScroller();
        }
    },
    
    afterLayout: function() {
        Ext.grid.Section.superclass.afterLayout.call(this);
        if (!this.hasGridView) {
            this.hasGridView = true;
            this.viewConfig = this.viewConfig || {};
            Ext.applyIf(this.viewConfig, {
                xtype: 'gridview',
                store: this.store,
                headerCt: this.headerCt,
                selModel: this.selModel,
                features: this.features,
                listeners: {
                    bodyscroll: this.onGridViewScroll,
                    scope: this
                }                
            });
            this.view = this.add(this.viewConfig);
            this.headerCt.view = this.view;
            Ext.Function.defer(this.determineScrollbars, 50, this);
            Ext.getBody().on('mousewheel', this.onMouseWheel, this);
        }
    },
        
    hideHorizontalScroller: function() {
        if (this.horizontalScroller.ownerCt === this) {
            this.verticalScroller.offsets.bottom = 0;
            this.removeDocked(this.horizontalScroller, false);    
        }
        
    },
    
    showHorizontalScroller: function() {
        this.verticalScroller.offsets.bottom = Ext.getScrollBarWidth() - 2;
        if (this.horizontalScroller.ownerCt !== this) {
            this.addDocked(this.horizontalScroller);
        }
        
    },
    
    hideVerticalScroller: function() {
        if (this.verticalScroller.ownerCt === this) {
            this.removeDocked(this.verticalScroller, false);
        }
    },
    
    showVerticalScroller: function() {
        if (this.verticalScroller.ownerCt !== this) {
            this.addDocked(this.verticalScroller);
        }
    },
    
    invalidateScroller: function() {
        this.up('gridpanel').invalidateScroller();
    },
    
    onGridViewScroll: function(e, t) {
        this.headerCt.el.dom.scrollLeft = t.scrollLeft;
    },

    onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
        this.view.refresh();
        //this.up('gridpanel').invalidateScroller();
    },
    
    // Section onHeaderHide is invoked after view.
    onHeaderHide: function(headerCt, header, idx) {
        this.invalidateScroller();
    },
    
    onHeaderShow: function(headerCt, header, idx) {
        this.invalidateScroller();
    },
    
    getLhsMarker: function() {
        if (!this.lhsMarker) {
            this.lhsMarker = Ext.core.DomHelper.append(this.el, {
                cls: Ext.baseCSSPrefix + 'grid-resize-marker'
            }, true);
        }
        return this.lhsMarker;
    },
    
    getRhsMarker: function() {
        if (!this.rhsMarker) {
            this.rhsMarker = Ext.core.DomHelper.append(this.el, {
                cls: Ext.baseCSSPrefix + 'grid-resize-marker'
            }, true);
        }
        return this.rhsMarker;
    },
    
    onMouseWheel: function(e) {
        var dock  = this.dock,
            browserEvent = e.browserEvent,
            vertDock = this.verticalScrollDock;

        if (e.within(this.el)) {
            e.stopEvent();
            
            // Webkit Horizontal Axis
            if (browserEvent.wheelDeltaX || browserEvent.wheelDeltaY) {
                this.horizontalScroller.scrollByDeltaX(-browserEvent.wheelDeltaX / 120 * this.scrollDelta / 6);
                this.verticalScroller.scrollByDeltaY(-browserEvent.wheelDeltaY / 120 * this.scrollDelta / 6);
            } else {
                // Gecko Horizontal Axis
                if (browserEvent.axis && browserEvent.axis === 1) {
                    this.horizontalScroller.scrollByDeltaX(-(this.scrollDelta * e.getWheelDelta()) / 6);
                } else {
                    this.verticalScroller.scrollByDeltaY(-(this.scrollDelta * e.getWheelDelta() / 6));
                }
            }
            
        }
    }

});
